/* 
 *  Created By: Tom Shirley
 *  Project URL: http://www.codeplex.com/accesschecker
 *  License: GNU GPL v2
 */
using System;
using System.Xml;
using System.Net;
using System.IO;
using System.Web;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Utilities;
using System.Web.UI.WebControls;

namespace TomShirley.WebParts.AccessChecker
{
    public partial class AccessCheckerWebPart : BaseWebPart<AccessCheckerEditorPart>
    {
        /// <summary>
        /// Downloads the access checker report.
        /// </summary>
        /// <param name="SharePointTreeView">The share point tree view.</param>
        /// <param name="ShowUserOrWebPermissions">The show user or web permissions.</param>
        /// <param name="PrincipalInfo">The principal info.</param>
        /// <param name="Access">The access.</param>
        internal void DownloadAccessCheckerReport(SPPermissionsTreeView SharePointTreeView, string ShowUserOrWebPermissions,
                                                  SPPrincipalInfo PrincipalInfo, SPRoleDefinition RoleDefinition, DateTime TimeGenerated)
        {
            if (SharePointTreeView == null)
                throw new ArgumentNullException("TreeView object cannot be null");

            if (SharePointTreeView.Nodes != null && SharePointTreeView.Nodes.Count > 0)
            {
                using (MemoryStream stream = new MemoryStream())
                {
                    XmlTextWriter writer = new XmlTextWriter(stream, System.Text.Encoding.UTF8);
                    writer.WriteStartDocument();
                    writer.WriteStartElement("AccessChecker");
                    writer.WriteElementString("TimeGenerated", TimeGenerated.ToString());
                    writer.WriteElementString("Mode", ShowUserOrWebPermissions);

                    if (ShowUserOrWebPermissions.Equals(AccessCheckerMode.User.ToString()))
                    {
                        writer.WriteStartElement("User");
                        writer.WriteElementString("DisplayName", PrincipalInfo.DisplayName);
                        writer.WriteElementString("Login", PrincipalInfo.LoginName);
                        writer.WriteEndElement();

                        writer.WriteElementString("Access", RoleDefinition.Name);
                    }

                    foreach (SPPermissionsTreeNode tNode in SharePointTreeView.Nodes)
                    {
                        SharePointTreeView.RemoveTreeNodeValuePathFromText(tNode);
                        WriteXmlNode(ShowUserOrWebPermissions, tNode, writer);
                    }

                    writer.WriteEndElement();
                    writer.WriteEndDocument();

                    writer.Flush();

                    // Convert the memory stream to an array of bytes.
                    byte[] byteArray = stream.ToArray();

                    // Send the XML file to the web browser for download.
                    this.Page.Response.Clear();

                    if (ShowUserOrWebPermissions.Equals(AccessCheckerMode.User.ToString()))
                        this.Page.Response.AppendHeader("Content-Disposition", "attachment;filename=\"" + GetReportFileName(PrincipalInfo.DisplayName, _CurrentWeb.ServerRelativeUrl) + "\"");
                    else
                        this.Page.Response.AppendHeader("Content-Disposition", "attachment;filename=\"" + GetReportFileName(_CurrentWeb.ServerRelativeUrl) + "\"");

                    this.Page.Response.AppendHeader("Content-Length", byteArray.Length.ToString());

                    this.Page.Response.ContentType = "text/xml";
                    this.Page.Response.BinaryWrite(byteArray);
                    this.Page.Response.End();
                    writer.Close();
                }
            }
        }

        /// <summary>
        /// Gets the name of the report file.
        /// </summary>
        /// <param name="UserDisplayName">Display name of the user.</param>
        /// <param name="serverRelativeURL">The server relative URL.</param>
        /// <returns></returns>
        private string GetReportFileName(string UserDisplayName, string serverRelativeURL)
        {
            string fileName = string.Empty;

            fileName = string.Format("{0} - Access Report for {1} - {2}.xml", _CurrentWeb.Title, UserDisplayName,
                                      DateTime.Now.ToUniversalTime().ToString("yyyyMMdd-hhmm"));
            return Common.ReplaceInvalidFileNameChars(fileName);
        }

        /// <summary>
        /// Gets the name of the report file.
        /// </summary>
        /// <param name="serverRelativeURL">The server relative URL.</param>
        /// <returns></returns>
        private string GetReportFileName(string serverRelativeURL)
        {
            string fileName = string.Empty;

            fileName = string.Format("{0} - Permission Inheritance Report - {1}.xml", _CurrentWeb.Title,
                                      DateTime.Now.ToUniversalTime().ToString("yyyyMMdd-hhmm"));
            return Common.ReplaceInvalidFileNameChars(fileName);
        }

        /// <summary>
        /// </summary>
        /// <returns></returns>
        internal void WriteXmlNode(string mode, TreeNode tnode, XmlWriter xmlWriter)
        {
            string[] valuePathArray = tnode.Value.Split('|');
            string elementName = "Access";
            int itemCountPosition = tnode.Text.LastIndexOf("(");

            xmlWriter.WriteStartElement(valuePathArray[0]);

            // If there is a left parenthesis then the node is a list node, so parse out the item count value
            if (itemCountPosition > 0)
            {
                xmlWriter.WriteElementString("Title", tnode.Text.Substring(0, itemCountPosition));
                xmlWriter.WriteElementString("ItemCount", tnode.Text.Substring(itemCountPosition + 1, (tnode.Text.LastIndexOf(")") - itemCountPosition) - 1));
            }
            else
            {
                xmlWriter.WriteElementString("Title", tnode.Text);
            }

            if (mode.Equals(AccessCheckerMode.Web.ToString()))
                elementName = "UniquePermissions";
            if (valuePathArray[2].Equals(PermissionType.MatchingPermissions.ToString()))
                xmlWriter.WriteElementString(elementName, "Yes");
            else
                xmlWriter.WriteElementString(elementName, "No");

            foreach (TreeNode currentNode in tnode.ChildNodes)
            {
                WriteXmlNode(mode, currentNode, xmlWriter);
            }

            xmlWriter.WriteEndElement();
        }
    }
}
